package com.bestv.search.management.datasyn;

import com.bestv.search.common.cache.SystemCache;
import com.bestv.search.common.dataSource.DataSourceKey;
import com.bestv.search.common.dataSource.DataSourceKeyUtil;
import com.bestv.search.common.model.ProgramSyncStatus;
import com.bestv.search.common.service.*;
import com.bestv.search.common.util.CharUtil;
import com.bestv.search.common.util.ChineseCharToEn;
import com.bestv.search.management.command.InfoHeaderCommand;
import net.paoding.analysis.analyzer.PaodingAnalyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public abstract class ProgramSyncerImpl implements ProgramSyncer {

    public static SimpleDateFormat timeformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static SimpleDateFormat yearformat = new SimpleDateFormat("yyyy");
    public static SimpleDateFormat updatetimeformat = new SimpleDateFormat("yyyyMMddHHmmss");
    static ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext-dao.xml",
            "applicationContext-resources.xml", "applicationContext-service.xml", "security.xml"});
    static InfoManager vm = (InfoManager) context.getBean("infoManager");
    static ProgramManager pm = (ProgramManager) context.getBean("programManager");
    static SeriesManager sm = (SeriesManager) context.getBean("seriesManager");
    static BizTypeManager bm = (BizTypeManager) context.getBean("bizTypeManager");
    static KeywordManager km = (KeywordManager) context.getBean("keywordManager");
    static TagManager tm = (TagManager) context.getBean("tagManager");
    static ScheduleManager schm = (ScheduleManager) context.getBean("scheduleManager");
    static ChannelManager cm = (ChannelManager) context.getBean("channelManager");
    static SystemCache systemCache = (SystemCache) context.getBean("systemCache");
    static ProgramSyncStatusManager psm = (ProgramSyncStatusManager) context.getBean("programSyncStatusManager");
    static InfoHeaderManager infoHeaderManager = (InfoHeaderManager) context.getBean("infoHeaderManager");
    static InfoHeaderItemManager infoHeaderItemManager = (InfoHeaderItemManager) context
            .getBean("infoHeaderItemManager");
    static InfoHeaderCommand infoHeaderCommand = (InfoHeaderCommand) context.getBean("infoHeaderCommand");
    Map<String, String> props = new HashMap<String, String>(0);

    boolean result = false;
    Date thisSyncTime = null;
    Date lastSyncSuccessfullTime = null;
    ProgramSyncStatus status = null;

    public void justDoIt() throws Exception {
        if (init(props)) {
            updateProgram();
            result = true;
        }
    }

    public abstract boolean init(Map<String, String> properties);

    public abstract boolean updateProgram() throws Exception;

    public void setProps(Map<String, String> props) {
        this.props = props;
    }

    protected void updateSyncStatus(String sysName, int serverNo, String fieldName, String syncMessage,
                                    Date syncSuccessfullTime) {
        // local site code equals to local data source Key.
        String siteCode = systemCache.getLocalDataSourceKey();
        DataSourceKey key = DataSourceKeyUtil.convert(siteCode);
        Date now = Calendar.getInstance().getTime();

        // update sync status to DB
        if (status == null) {
            status = new ProgramSyncStatus();
            status.setSiteCode(systemCache.getLocalDataSourceKey());
            status.setSysName(sysName);
            status.setServerNo(serverNo);
            status.setFieldName(fieldName);
        }
        status.setLastSyncTime(now);
        status.setUpdateTime(now);
        if (syncMessage.startsWith("Success")) {
            // When sync successful, set LastSyncSuccessTime
            status.setSyncSuccessTime(syncSuccessfullTime);
        }
        status.setSyncMessage(syncMessage);

        // Save to DB
        psm.saveOrUpdate(key, status);
    }

    @SuppressWarnings("deprecation")
    protected String splitToken(String word) {
        StringBuffer sb = new StringBuffer();
        PaodingAnalyzer analyzer = new PaodingAnalyzer();
        StringReader reader = new StringReader(word);
        TokenStream ts = analyzer.tokenStream("", reader);
        Token token;
        try {
            while ((token = ts.next()) != null) {
                String text = ChineseCharToEn.getAllFirstLetter(token.term());
                sb.append(text).append(" ").append(CharUtil.charToNum(text)).append(" ");
            }
        } catch (IOException e) {
            logger.error(e);
        }
        return sb.toString();
    }

    protected boolean initLastSyncTime(String sysName, int serverNo, String fieldName) {
        // local site code equals to local data source Key.
        String siteCode = systemCache.getLocalDataSourceKey();
        DataSourceKey key = DataSourceKeyUtil.convert(siteCode);

        status = psm.get(key, siteCode, sysName, serverNo, fieldName);
        if (status == null) {
            lastSyncSuccessfullTime = new Date(4);
            logger.info("last" + fieldName + " is empty, start a full volume sync!");
        } else {
            lastSyncSuccessfullTime = status.getSyncSuccessTime();
        }
        if (new Date().before(lastSyncSuccessfullTime)) {
            logger.warn("current time before lastSeriesSyncTime");
            result = false;
            return false;
        }

        return true;
    }
}
